/*
===========================================================================

Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.

This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").

Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/

#ifndef __P_LOCAL__
#define __P_LOCAL__

#ifndef __R_LOCAL__
	#include "r_local.h"
#endif

#define FLOATSPEED		(FRACUNIT*4)


#define MAXHEALTH		100
#define VIEWHEIGHT		(41*FRACUNIT)

// mapblocks are used to check movement
// against lines and things
#define MAPBLOCKUNITS	128
#define MAPBLOCKSIZE	(MAPBLOCKUNITS*FRACUNIT)
#define MAPBLOCKSHIFT	(FRACBITS+7)
#define MAPBMASK		(MAPBLOCKSIZE-1)
#define MAPBTOFRAC		(MAPBLOCKSHIFT-FRACBITS)


// player radius for movement checking
#define PLAYERRADIUS	16*FRACUNIT

// MAXRADIUS is for precalculated sector block boxes
// the spider demon is larger,
// but we do not have any moving sectors nearby
#define MAXRADIUS		32*FRACUNIT

#define GRAVITY		FRACUNIT
#define MAXMOVE		(30*FRACUNIT)

#define USERANGE		(64*FRACUNIT)
#define MELEERANGE		(64*FRACUNIT)
#define MISSILERANGE	(32*64*FRACUNIT)

// follow a player exlusively for 3 seconds
#define	BASETHRESHOLD	 	100



//
// P_TICK
//

// both the head and tail of the thinker list
extern	thinker_t	thinkercap;


void P_InitThinkers( void );
void P_AddThinker( thinker_t* thinker );
void P_RemoveThinker( thinker_t* thinker );


//
// P_PSPR
//
void P_SetupPsprites( player_t* curplayer );
void P_MovePsprites( player_t* curplayer );
void P_DropWeapon( player_t* player );


//
// P_USER
//
void	P_PlayerThink( player_t* player );


//
// P_MOBJ
//
#define ONFLOORZ		MININT
#define ONCEILINGZ		MAXINT

// Time interval for item respawning.
#define ITEMQUESIZE		128

extern mapthing_t	itemrespawnque[ITEMQUESIZE];
extern int		itemrespawntime[ITEMQUESIZE];
extern int		iquehead;
extern int		iquetail;


void P_RespawnSpecials( void );

mobj_t*
P_SpawnMobj
( fixed_t	x,
  fixed_t	y,
  fixed_t	z,
  mobjtype_t	type );

void 	P_RemoveMobj( mobj_t* th );
qboolean	P_SetMobjState( mobj_t* mobj, statenum_t state );
void 	P_MobjThinker( mobj_t* mobj );

void	P_SpawnPuff( fixed_t x, fixed_t y, fixed_t z );
void 	P_SpawnBlood( fixed_t x, fixed_t y, fixed_t z, int damage );
mobj_t* P_SpawnMissile( mobj_t* source, mobj_t* dest, mobjtype_t type );
void	P_SpawnPlayerMissile( mobj_t* source, mobjtype_t type );


//
// P_ENEMY
//
void P_NoiseAlert( mobj_t* target, mobj_t* emmiter );


//
// P_MAPUTL
//
typedef struct
{
	fixed_t	x;
	fixed_t	y;
	fixed_t	dx;
	fixed_t	dy;

} divline_t;

typedef struct
{
	fixed_t	frac;		// along trace line
	qboolean	isaline;
	union
	{
		mobj_t*	thing;
		line_t*	line;
	}			d;
} intercept_t;

#define MAXINTERCEPTS	128

extern intercept_t	intercepts[MAXINTERCEPTS];
extern intercept_t*	intercept_p;

typedef qboolean( *traverser_t )( intercept_t* in );

fixed_t P_AproxDistance( fixed_t dx, fixed_t dy );
int 	P_PointOnLineSide( fixed_t x, fixed_t y, line_t* line );
int 	P_PointOnDivlineSide( fixed_t x, fixed_t y, divline_t* line );
void 	P_MakeDivline( line_t* li, divline_t* dl );
fixed_t P_InterceptVector( divline_t* v2, divline_t* v1 );
int 	P_BoxOnLineSide( fixed_t* tmbox, line_t* ld );

extern fixed_t		opentop;
extern fixed_t 		openbottom;
extern fixed_t		openrange;
extern fixed_t		lowfloor;

void 	P_LineOpening( line_t* linedef );

qboolean P_BlockLinesIterator( int x, int y, qboolean( *func )( line_t* ) );
qboolean P_BlockThingsIterator( int x, int y, qboolean( *func )( mobj_t* ) );

#define PT_ADDLINES		1
#define PT_ADDTHINGS	2
#define PT_EARLYOUT		4

extern divline_t	trace;

qboolean
P_PathTraverse
( fixed_t	x1,
  fixed_t	y1,
  fixed_t	x2,
  fixed_t	y2,
  int		flags,
  qboolean( *trav )( intercept_t* ) );

void P_UnsetThingPosition( mobj_t* thing );
void P_SetThingPosition( mobj_t* thing );


//
// P_MAP
//

// If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz".
extern qboolean		floatok;
extern fixed_t		tmfloorz;
extern fixed_t		tmceilingz;


extern	line_t*		ceilingline;

qboolean P_CheckPosition( mobj_t* thing, fixed_t x, fixed_t y );
qboolean P_TryMove( mobj_t* thing, fixed_t x, fixed_t y );
qboolean P_TeleportMove( mobj_t* thing, fixed_t x, fixed_t y );
void	P_SlideMove( mobj_t* mo );
qboolean P_CheckSight( mobj_t* t1, mobj_t* t2 );
void 	P_UseLines( player_t* player );

qboolean P_ChangeSector( sector_t* sector, qboolean crunch );

extern mobj_t*	linetarget;	// who got hit (or NULL)

fixed_t
P_AimLineAttack
( mobj_t*	t1,
  angle_t	angle,
  fixed_t	distance );

void
P_LineAttack
( mobj_t*	t1,
  angle_t	angle,
  fixed_t	distance,
  fixed_t	slope,
  int		damage );

void
P_RadiusAttack
( mobj_t*	spot,
  mobj_t*	source,
  int		damage );



//
// P_SETUP
//


//
// P_INTER
//
extern const int		maxammo[NUMAMMO];
extern const int		clipammo[NUMAMMO];

void
P_TouchSpecialThing
( mobj_t*	special,
  mobj_t*	toucher );

void
P_DamageMobj
( mobj_t*	target,
  mobj_t*	inflictor,
  mobj_t*	source,
  int		damage );


//
// P_SPEC
//
#include "p_spec.h"


#endif	// __P_LOCAL__



